#                    			      Gnarly Makefile
#				            Michael M Vitousek
#               
# Commonly used targets:
#	make, make bytecode	 	Creates Ocaml bytecode for Gnarly.
#	make bin, make exe		Creates a native binary for Gnarly (named "gnarly" if <make bin> is called, 
#						or "gnarly.exe" if <make exe> is called).
#	make doc, make doc-html		Creates HTML documents, documenting Gnarly's functionality.
#	make doc-latex			Creates a PDF using LaTeX, documenting Gnarly's functionality.
#	make papers			Creates PDFs using LaTeX, showing the relevant papers attached to this project.
#	make clean			Cleans up bytecode, native code, executables, documentation, and papers.
#       make spc                        Makes something useful to me at any given point in time. Should be removed when project is complete
#
#
TITLE = "The Gnarly Programming Language"
VERSION = 0.7.3


# Defining directories
BIN = bin
SRC = src
DOC = doc
PAPERSRC = latex
PAPERS = doc/papers


# Tool options
OCCFLAGS := -I $(BIN)
OCOPTFLAGS := -I $(BIN)
OCDOCFLAGS := -I $(BIN) -t $(TITLE) 
OCYACCFLAGS :=
OCLEXFLAGS :=
TEXFLAGS := 
BIBFLAGS :=
RMFLAGS := -f


# Defining tools
OCC = ocamlc $(OCCFLAGS)
OCOPT = ocamlopt $(OCOPTFLAGS)
OCDOC = ocamldoc $(OCDOCFLAGS)
OCYACC = ocamlyacc $(OCYACCFLAGS)
OCLEX = ocamllex $(OCLEXFLAGS)
TEX = pdflatex $(TEXFLAGS)
BIB = bibtex $(BIBFLAGS)
RM = rm $(RMFLAGS)


# Defining groups
SOURCES := $(addprefix $(SRC)/, gnsyn.ml printing.ml sinterp.ml interp.ml interface.ml primitives.ml gnarly.ml)
ALLSOURCES := $(addprefix $(BIN)/, lexer.ml grammar.ml) $(SOURCES)
BYTECODE := $(addprefix $(BIN)/, gnsyn.cmo lexer.cmo grammar.cmo printing.cmo sinterp.cmo interp.cmo interface.cmo primitives.cmo gnarly.cmo)
NATIVE := $(addprefix $(BIN)/, gnsyn.cmx lexer.cmx grammar.cmx printing.cmx sinterp.cmx interp.cmx interface.cmx primitives.cmx gnarly.cmx)
PAPERNAMES := Review Bibliography Proposal
PAPERSOURCES := $(addprefix $(PAPERSRC)/, $(addsuffix .tex, $(PAPERNAMES)))
PAPEROUTPUTS := $(addprefix $(PAPERS)/, $(addsuffix .pdf, $(PAPERNAMES)))

# All should make Gnarly bytecode for fast testing
.PHONY : all
all : bytecode


# Implicit rules
$(BIN)/%.cmo : $(SRC)/%.ml
	$(OCC) -o $@ -c $<
$(BIN)/%.cmx : $(SRC)/%.ml
	$(OCOPT) -o $@ -c $<
$(PAPERS)/%.pdf : $(PAPERSRC)/%.tex
	$(TEX) -output-directory $(PAPERS) $<
	$(BIB) $(basename $@)
	$(TEX) -output-directory $(PAPERS) $<
	$(TEX) -output-directory $(PAPERS) $<


# First step in compiling lexer and grammar using Lex and Yacc
$(BIN)/grammar.ml : $(SRC)/grammar.mly
	$(OCYACC) -b $(BIN)/grammar $(SRC)/grammar.mly

$(BIN)/lexer.ml : $(SRC)/lexer.mll
	$(OCLEX) -o $(BIN)/lexer.ml $(SRC)/lexer.mll


# Make an Ocaml bytecode executable for Gnarly
.PHONY : bytecode
bytecode : $(BYTECODE)
	$(RM) $(BIN)/gnarly
	$(OCC) -o $(BIN)/gnarly $(BYTECODE)

$(BIN)/gnarly.cmo : $(BIN)/printing.cmo $(BIN)/interface.cmo $(BIN)/primitives.cmo $(SRC)/gnarly.ml
$(BIN)/gnsyn.cmo : $(SRC)/gnsyn.ml
$(BIN)/printing.cmo : $(BIN)/gnsyn.cmo $(SRC)/printing.ml
$(BIN)/interp.cmo : $(BIN)/gnsyn.cmo $(BIN)/printing.cmo $(BIN)/sinterp.cmo $(SRC)/interp.ml
$(BIN)/sinterp.cmo : $(BIN)/gnsyn.cmo $(BIN)/printing.cmo $(SRC)/sinterp.ml
$(BIN)/interface.cmo : $(BIN)/gnsyn.cmo $(BIN)/grammar.cmo $(BIN)/lexer.cmo $(BIN)/printing.cmo $(BIN)/sinterp.cmo $(BIN)/interp.cmo $(SRC)/interface.ml
$(BIN)/primitives.cmo : $(BIN)/gnsyn.cmo $(BIN)/printing.cmo $(BIN)/interp.cmo $(BIN)/interface.cmo $(SRC)/primitives.ml

$(BIN)/lexer.cmo : $(BIN)/grammar.cmo $(BIN)/lexer.ml
	$(OCC) -o $@ -c $(BIN)/lexer.ml

$(BIN)/grammar.cmo : $(BIN)/gnsyn.cmo $(BIN)/grammar.ml
	$(OCC) -o $(BIN)/grammar.cmi -c $(BIN)/grammar.mli
	$(OCC) -o $@ -c $(BIN)/grammar.ml


# Two options for native code compilation, exe and bin, different only in that exe adds the file extension ".exe" to the generated binary.
.PHONY: exe bin
exe: $(NATIVE)
	$(RM) $(BIN)/gnarly-$(VERSION).exe
	$(OCOPT) -o $(BIN)/gnarly-$(VERSION).exe $(NATIVE)

bin : $(NATIVE)
	$(RM) $(BIN)/gnarly-$(VERSION)
	$(OCOPT) -o $(BIN)/gnarly-$(VERSION) $(NATIVE)

$(BIN)/gnarly.cmx : $(BIN)/printing.cmx $(BIN)/interface.cmx $(BIN)/primitives.cmx $(SRC)/gnarly.ml
$(BIN)/gnsyn.cmx : $(SRC)/gnsyn.ml
$(BIN)/printing.cmx : $(BIN)/gnsyn.cmx $(SRC)/printing.ml
$(BIN)/interp.cmx : $(BIN)/gnsyn.cmx $(BIN)/printing.cmx $(BIN)/sinterp.cmx $(SRC)/interp.ml
$(BIN)/sinterp.cmx : $(BIN)/gnsyn.cmx $(BIN)/printing.cmx $(SRC)/sinterp.ml
$(BIN)/interface.cmx : $(BIN)/gnsyn.cmx $(BIN)/grammar.cmx $(BIN)/lexer.cmx $(BIN)/printing.cmx $(BIN)/sinterp.cmx $(BIN)/interp.cmx $(SRC)/interface.ml
$(BIN)/primitives.cmx : $(BIN)/gnsyn.cmx $(BIN)/printing.cmx $(BIN)/interp.cmx $(BIN)/interface.cmx $(SRC)/primitives.ml

$(BIN)/lexer.cmx : $(BIN)/grammar.cmx $(BIN)/lexer.ml
	$(OCOPT) -o $@ -c $(BIN)/lexer.ml

$(BIN)/grammar.cmx : $(BIN)/gnsyn.cmx $(BIN)/grammar.ml
	$(OCOPT) -o $(BIN)/grammar.cmi -c $(BIN)/grammar.mli
	$(OCOPT) -o $@ -c $(BIN)/grammar.ml


# Documentation defaults to HTML
.PHONY : doc docs
doc : doc-html
docs : doc


# HTML documentation generation
.PHONY : html-doc
doc-html : $(ALLSOURCES) $(BYTECODE)
	$(OCDOC) -html -d $(DOC) $(ALLSOURCES)


# LaTeX documentation generation
.PHONY : latex-doc
doc-latex : $(ALLSOURCES) $(BYTECODE)
	$(OCDOC) -latex -o $(DOC)/gnarly.tex $(ALLSOURCES)
	$(TEX) -output-directory $(DOC) $(DOC)/gnarly.tex


# LaTeX-ing associated papers
.PHONY: papers
papers: $(PAPERSRC)/SelectedBibliography.bib $(PAPERSOURCES) $(PAPEROUTPUTS)


# Cleaning up
.PHONY : clean
clean : clean-binaries clean-modules clean-doc clean-papers

.PHONY : clean-binaries cb
clean-binaries : 
	$(RM) $(BIN)/gnarly-$(VERSION).exe $(BIN)/gnarly-$(VERSION) $(BIN)/gnarly
cb : clean-binaries

.PHONY : clean-modules cm
clean-modules : 
	$(RM) $(BIN)/*.cmo $(BIN)/*.cmi $(BIN)/*.cmx $(BIN)/*.o $(BIN)/grammar.mli $(BIN)/grammar.ml $(BIN)/lexer.ml
cm : clean-modules

.PHONY : clean-doc clean-docs cd
clean-doc : clean-modules
	$(RM) $(DOC)/*.html $(DOC)/style.css $(DOC)/*.tex $(DOC)/*.pdf $(DOC)/*.aux $(DOC)/*.toc $(DOC)/*.log $(DOC)/ocamldoc.sty
clean-docs : clean-doc
cd : clean-doc

.PHONY : clean-papers cp
clean-papers :
	$(RM) $(PAPERS)/*.aux $(PAPERS)/*.bbl $(PAPERS)/*.blg $(PAPERS)/*.log $(PAPERS)/*.pdf
cp : clean-papers